#ifndef __FONT_H__
#define __FONT_H__

// C header
#include <stdlib.h>
#include <stdio.h>

//////////////////////////////////////////////////////////////////////////
// || sentance split
// |  word split
// ^>> continue page
// ^>| confirm change page
// #[0-9]\(|[0-9]\)* push color stack
// #[^0-9]pop color stack
//////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
//#define _DEBUG_FONT
#endif
#include "chartable.h"

#ifdef _DEBUG_FONT
#define FONT_COLON			':'
#define FONT_SLASH			'/'
#define	FONT_SPACE			' '
#define	FONT_POUND			'#'
#define	FONT_PERCENT		'%'
#define	FONT_STAR			'*'
#define	FONT_PLUS			'+'
#define	FONT_MINUS			'-'
#define	FONT_POINT			'.'
#define	FONT_XOR			'^'
#define FONT_GTR            '>'
#define FONT_LSS			'<'
#define	FONT_STICK			'|'
#define	FONT_NUM_0			'0'
#define	FONT_NUM_1			'1'
#define	FONT_NUM_2			'2'
#define	FONT_NUM_3			'3'
#define	FONT_NUM_4			'4'
#define	FONT_NUM_5			'5'
#define	FONT_NUM_6			'6'
#define	FONT_NUM_7			'7'
#define	FONT_NUM_8			'8'
#define	FONT_NUM_9			'9'
#define	FONT_UPPERCASE_A	'A'
#define	FONT_UPPERCASE_B	'B'
#define	FONT_UPPERCASE_C	'C'
#define	FONT_UPPERCASE_D	'D'
#define	FONT_UPPERCASE_E	'E'
#define	FONT_UPPERCASE_F	'F'
#define	FONT_UPPERCASE_G	'G'
#define	FONT_UPPERCASE_H	'H'
#define	FONT_UPPERCASE_I	'I'
#define	FONT_UPPERCASE_J	'J'
#define	FONT_UPPERCASE_K	'K'
#define	FONT_UPPERCASE_L	'L'
#define	FONT_UPPERCASE_M	'M'
#define	FONT_UPPERCASE_N	'N'
#define	FONT_UPPERCASE_O	'O'
#define	FONT_UPPERCASE_P	'P'
#define	FONT_UPPERCASE_Q	'Q'
#define	FONT_UPPERCASE_R	'R'
#define	FONT_UPPERCASE_S	'S'
#define	FONT_UPPERCASE_T	'T'
#define	FONT_UPPERCASE_U	'U'
#define	FONT_UPPERCASE_V	'V'
#define	FONT_UPPERCASE_W	'W'
#define	FONT_UPPERCASE_X	'X'
#define	FONT_UPPERCASE_Y	'Y'
#define	FONT_UPPERCASE_Z	'Z'
#define	FONT_LOWERCASE_A	'a'
#define	FONT_LOWERCASE_B	'b'
#define	FONT_LOWERCASE_C	'c'
#define	FONT_LOWERCASE_D	'd'
#define	FONT_LOWERCASE_E	'e'
#define	FONT_LOWERCASE_F	'f'
#define	FONT_LOWERCASE_G	'g'
#define	FONT_LOWERCASE_H	'h'
#define	FONT_LOWERCASE_I	'i'
#define	FONT_LOWERCASE_J	'j'
#define	FONT_LOWERCASE_K	'k'
#define	FONT_LOWERCASE_L	'l'
#define	FONT_LOWERCASE_M	'm'
#define	FONT_LOWERCASE_N	'n'
#define	FONT_LOWERCASE_O	'o'
#define	FONT_LOWERCASE_P	'p'
#define	FONT_LOWERCASE_Q	'q'
#define	FONT_LOWERCASE_R	'r'
#define	FONT_LOWERCASE_S	's'
#define	FONT_LOWERCASE_T	't'
#define	FONT_LOWERCASE_U	'u'
#define	FONT_LOWERCASE_V	'v'
#define	FONT_LOWERCASE_W	'w'
#define	FONT_LOWERCASE_X	'x'
#define	FONT_LOWERCASE_Y	'y'
#define	FONT_LOWERCASE_Z	'z'
#else
#define FONT_COLON			MAP_COLON
#define FONT_SLASH			MAP_SLASH
#define FONT_COMMA          MAP_COMMA
#define	FONT_SPACE			MAP_SPACE
#define	FONT_POUND			MAP_POUND
#define	FONT_PERCENT		MAP_PERCENT
#define	FONT_STAR			MAP_STAR
#define	FONT_PLUS			MAP_PLUS
#define	FONT_MINUS			MAP_MINUS
#define	FONT_POINT			MAP_POINT
#define	FONT_XOR			MAP_XOR
#define	FONT_STICK			MAP_STICK
#define FONT_GTR            MAP_GTR
#define FONT_LSS			MAP_LSS
#define FONT_GRADS			MAP_UPPERO
#define	FONT_NUM_0			MAP_NUM_0
#define	FONT_NUM_1			MAP_NUM_1
#define	FONT_NUM_2			MAP_NUM_2
#define	FONT_NUM_3			MAP_NUM_3
#define	FONT_NUM_4			MAP_NUM_4
#define	FONT_NUM_5			MAP_NUM_5
#define	FONT_NUM_6			MAP_NUM_6
#define	FONT_NUM_7			MAP_NUM_7
#define	FONT_NUM_8			MAP_NUM_8
#define	FONT_NUM_9			MAP_NUM_9
#define	FONT_UPPERCASE_A	MAP_UPPERCASE_A
#define	FONT_UPPERCASE_B	MAP_UPPERCASE_B
#define	FONT_UPPERCASE_C	MAP_UPPERCASE_C
#define	FONT_UPPERCASE_D	MAP_UPPERCASE_D
#define	FONT_UPPERCASE_E	MAP_UPPERCASE_E
#define	FONT_UPPERCASE_F	MAP_UPPERCASE_F
#define	FONT_UPPERCASE_G	MAP_UPPERCASE_G
#define	FONT_UPPERCASE_H	MAP_UPPERCASE_H
#define	FONT_UPPERCASE_I	MAP_UPPERCASE_I
#define	FONT_UPPERCASE_J	MAP_UPPERCASE_J
#define	FONT_UPPERCASE_K	MAP_UPPERCASE_K
#define	FONT_UPPERCASE_L	MAP_UPPERCASE_L
#define	FONT_UPPERCASE_M	MAP_UPPERCASE_M
#define	FONT_UPPERCASE_N	MAP_UPPERCASE_N
#define	FONT_UPPERCASE_O	MAP_UPPERCASE_O
#define	FONT_UPPERCASE_P	MAP_UPPERCASE_P
#define	FONT_UPPERCASE_Q	MAP_UPPERCASE_Q
#define	FONT_UPPERCASE_R	MAP_UPPERCASE_R
#define	FONT_UPPERCASE_S	MAP_UPPERCASE_S
#define	FONT_UPPERCASE_T	MAP_UPPERCASE_T
#define	FONT_UPPERCASE_U	MAP_UPPERCASE_U
#define	FONT_UPPERCASE_V	MAP_UPPERCASE_V
#define	FONT_UPPERCASE_W	MAP_UPPERCASE_W
#define	FONT_UPPERCASE_X	MAP_UPPERCASE_X
#define	FONT_UPPERCASE_Y	MAP_UPPERCASE_Y
#define	FONT_UPPERCASE_Z	MAP_UPPERCASE_Z
#define	FONT_LOWERCASE_A	MAP_LOWERCASE_A
#define	FONT_LOWERCASE_B	MAP_LOWERCASE_B
#define	FONT_LOWERCASE_C	MAP_LOWERCASE_C
#define	FONT_LOWERCASE_D	MAP_LOWERCASE_D
#define	FONT_LOWERCASE_E	MAP_LOWERCASE_E
#define	FONT_LOWERCASE_F	MAP_LOWERCASE_F
#define	FONT_LOWERCASE_G	MAP_LOWERCASE_G
#define	FONT_LOWERCASE_H	MAP_LOWERCASE_H
#define	FONT_LOWERCASE_I	MAP_LOWERCASE_I
#define	FONT_LOWERCASE_J	MAP_LOWERCASE_J
#define	FONT_LOWERCASE_K	MAP_LOWERCASE_K
#define	FONT_LOWERCASE_L	MAP_LOWERCASE_L
#define	FONT_LOWERCASE_M	MAP_LOWERCASE_M
#define	FONT_LOWERCASE_N	MAP_LOWERCASE_N
#define	FONT_LOWERCASE_O	MAP_LOWERCASE_O
#define	FONT_LOWERCASE_P	MAP_LOWERCASE_P
#define	FONT_LOWERCASE_Q	MAP_LOWERCASE_Q
#define	FONT_LOWERCASE_R	MAP_LOWERCASE_R
#define	FONT_LOWERCASE_S	MAP_LOWERCASE_S
#define	FONT_LOWERCASE_T	MAP_LOWERCASE_T
#define	FONT_LOWERCASE_U	MAP_LOWERCASE_U
#define	FONT_LOWERCASE_V	MAP_LOWERCASE_V
#define	FONT_LOWERCASE_W	MAP_LOWERCASE_W
#define	FONT_LOWERCASE_X	MAP_LOWERCASE_X
#define	FONT_LOWERCASE_Y	MAP_LOWERCASE_Y
#define	FONT_LOWERCASE_Z	MAP_LOWERCASE_Z
#define FONT_JAP_DOT		MAP_JAP_DOT
#endif

#include "../PreDefine.h"
class ASprite;

const int SPRITE_JAPANESE_COUNT = 2;
#define MAX_TEX_COLOR_NUM 3
class Font
{
public:
	Font(void);
	~Font(void);

	enum FontStyle{
		FontSmall = 0,
		FontTitle,
		FontGame,
		FontNormal,
		FontNormalSmall,
		FontExtra,
		FontCount,
		FontUser
	};
	enum ControlFlag{
		FLAG_NONE =	0,
		FLAG_PUSH_COLOR,
		FLAG_POP_COLOR,
		FLAG_SPACE,
		FLAG_WORD,
		FLAG_SENTANCE,
		FLAG_PAGE_CONTINUE,
		FLAG_PAGE_STOP
	};
	enum{
		Left    =  1<<1,
		Top     =  1<<2,
		Bottom  =  1<<3,
		Right   =  1<<4,
		HCenter =   Left | Right,
		VCenter =    Top | Bottom,
		Middle  = HCenter| VCenter
	};

	typedef int TextAlign;
	typedef int FontAlign;
	enum TextColor{
		Blue = 0,
		Red  = 1,
		Blue01 = 2
	};
	//bool DrawText(const char *text, int x, int y, FontStyle font = FontSmall, int align = Left, int nTextLength = -1);
	bool DrawText2(float x, float y, int align, const GL_TCHAR *fmt,...);
	bool DrawTextNumber2(float x,float y, int align,const GL_TCHAR *fmt, int d);
	bool DrawNumber(int num,int x, int y, int align=Left|Top);
	bool DrawNumber2(int num,int x, int y, int align=Left|Top, bool endingDot = false);
	bool DrawPercent(int num,int x, int y, int align=Left|Top);
	int DrawCelcius(int num,int x, int y, int align=Left|Top);
	bool DrawTime(tIPLTime& t,int x, int y, int align=Left|Top);

	bool DrawMultiText(const GL_TCHAR *text,int x, int y, const int nLinesLength[],int nTextDisplayLength, int textAlign, bool forceShadow = false);
	bool DrawMultiText(const GL_TCHAR *text,int x, int y,size_t length, int textAlign, int _dialogWidth = SCREEN_WIDTH, int _dialogHeight = SCREEN_HEIGHT_D2);
	bool DrawTextRotated(const GL_TCHAR *text,int x, int y, T_F32 angle);
	int GetTextLines(const GL_TCHAR *text, int & nMaxWidth, int &nMaxHeight,int &nMaxLine,
	int* nLinesLength = NULL, unsigned int nTextLength = -1);
#ifdef _OptimizePaintFrame
	void BeginOutIn(const GL_TCHAR *text, T_S32 objIdx, T_F32 inScale = 1.0f, T_S32 ox = MAGIC_NUM, T_S32 oy = MAGIC_NUM);
	void EndOutIn();
#endif
	void DrawText2OutIn(const GL_TCHAR *text,int x, int y, size_t length=-1,int align=Left|Top);

public:
	enum CharMapCategory {
		CM_SYMBOLS  = 0,
		CM_NUM,
		CM_UPPERCASE,
		CM_LOWERCASE,
		CM_EXTENDCASE,
		CM_JANPANESE,
		CM_COUNT
	};
	ASprite * mpASprite;
	int mpUseJapanese;


	static ASprite* mpJapinese[SPRITE_JAPANESE_COUNT];
	static int miGapXJapanese[SPRITE_JAPANESE_COUNT];
	static int miGapYJapanese[SPRITE_JAPANESE_COUNT];

	static void InitJapaneseFont();
	static void ReleaseJapaneseFont();
private:
	int mCharSectionMap[CM_COUNT];
	CharMapCategory GetCharCategory(GL_UCHAR charIndex);
	int  GetFrameIndex(GL_UCHAR charIndex);
	GL_UCHAR GetIndexFromChar(const GL_TCHAR* &ch);
	bool mbNeedFree;
	int mclrLayerIdx;
	int mclrStackHead;
	int currentTexture;
	int mTexStackHead;
	int miTexColor[MAX_TEX_COLOR_NUM][2];
	int miTexColorNum;
	int miAnchor;
	ASprite* _curAsprite;
	ControlFlag SkipWhiteSpace(const GL_TCHAR* & text, int& ow);
public:
	int miCurrentAlpha;
	int miSpaceWidth,miSpaceHeight;
	int miGapX,miGapY;
	ControlFlag  ControlText(const GL_TCHAR* &text, int &ox, int&oy);
	void AlignText(const GL_TCHAR*text, int &x, int &y, size_t &length,int align);
	ControlFlag SkipChar(const GL_TCHAR* &text,int &ox);
	ControlFlag SkipWord(const GL_TCHAR* &text,int &ox);
	int SkipWord(const GL_TCHAR*text);
	void Release();
	inline void SetSpaceSize(int dx, int dy){ miSpaceWidth = dx;miSpaceHeight=dy;}
	inline void SetSpaceSize(int dx) {miSpaceWidth = dx;miSpaceHeight=dx;}
	void SetColor(int index);
	void SetTexColor(int c1,...);
	void PushColor(){mTexStackHead=mclrStackHead;}
	int GetCharWidth(const GL_TCHAR *ch);
	int DrawChar(const GL_TCHAR *ch,int x, int y,int align=Left|Top);
	void SetGap(int dx){miGapX = miGapY = dx;}
	void SetGap(int dx,int dy){ miGapX = dx;miGapY = dy;}
	int GetTextWidth2(const GL_TCHAR*text,  size_t length  = -1);
	int GetTextHeight2(const GL_TCHAR*text, size_t length  = -1);
	bool DrawText(const GL_TCHAR *text,float x, float y, size_t length,int align);
	bool DrawText2(const GL_TCHAR *text,float x, float y, size_t length,int align);
	inline void ResetColor(){mclrLayerIdx = Blue;}
	inline void LoadFontImage(const char*filename);
	inline bool DrawText2(const GL_TCHAR *text,float x, float y){ return DrawText2(text, x, y, -1,Left|Top);}
	void SetFont2(ASprite*pFont, FontStyle style, bool bNeedFree=true,int anchor = Left|Top);
	void SetSectionMap(CharMapCategory category, int value){ mCharSectionMap[category]   = value;}
	void LoadTitleFont();
	void LoadGameFont();
	void LoadSmallFont2();
	void LoadNoramlFont2();
	void LoadNormalSmallFont();
	void LoadExtraFont2();
	void SetJapaneseAsprite();
	void DrawShadow(const GL_TCHAR *text,int x, int y, size_t length, int align, bool forceShadow = false);

	int GetCharIndex(const GL_TCHAR *text, GL_TCHAR *str);

	static int  sprintf(GL_TCHAR* buf, const GL_TCHAR* fmt,...);
	static int Font::vsprintf(GL_TCHAR *buf, const GL_TCHAR *fmt, va_list args);
	static GL_TCHAR* strucpy(GL_TCHAR* src,const GL_TCHAR* dst,size_t length =-1);

	inline static char* StrCpy(char*src,const char*dst)
	{
		return strcpy(src,dst);
	}
	inline static size_t StrLen(const char*str)
	{
		return strlen(str);
	}
	inline static int StrCmp(const char*s1, const char*s2)
	{
		return strcmp(s1,s2);
	}


	inline static GL_TCHAR* StrCpy(GL_TCHAR*src,const GL_TCHAR*dst)
	{
		if(!dst)
			*src=0;
		else
			strcpy((char*)src,(const char*)dst);
		return (GL_TCHAR*)src;
	}
	inline static size_t StrLen(const GL_TCHAR*str)
	{
		return strlen((const char*)str);
	}
	inline static int StrCmp(const GL_TCHAR*s1, const GL_TCHAR*s2)
	{
		return strcmp((const char*)s1,(const char*)s2);
	}
	inline static GL_TCHAR* StrCat(GL_TCHAR*s1, const GL_TCHAR*s2)
	{
		return (GL_TCHAR*)strcat((char*)s1,(const char*)s2);
	}
};
#define TEXT_MAX_LINES 200
#endif
